require("dotenv").config();
const express = require("express");
const cors = require("cors");
const helmet = require("helmet");
const https = require("https");
const http = require("http");
const config = require("./config");
const CacheManager = require("./utils/cache");
const RateLimiter = require("./utils/rateLimiter");

/**
 * 精简的点云缓存代理服务器
 * 核心功能：缓存 + 返回
 */
class ProxyServer {
  constructor() {
    this.app = express();
    this.cache = new CacheManager(config);
    this.rateLimiter = new RateLimiter({
      maxConcurrentRequests: config.rateLimiting.maxConcurrentRequests,
      queueTimeout: config.rateLimiting.queueTimeout,
    });

    // 创建复用的 HTTPS Agent
    this.httpsAgent = new https.Agent({
      rejectUnauthorized: process.env.NODE_ENV === "production",
      keepAlive: true,
      maxSockets: 10,
      maxFreeSockets: 3,
      timeout: 30000,
    });

    this.httpAgent = new http.Agent({
      keepAlive: true,
      maxSockets: 10,
      maxFreeSockets: 3,
      timeout: 30000,
    });

    this.setupMiddleware();
    this.setupRoutes();
  }

  /**
   * 设置中间件
   */
  setupMiddleware() {
    this.app.use(helmet());
    this.app.use(cors());
    
    
    // 移除JSON解析中间件 - 代理服务器不需要解析JSON请求体
  }

  /**
   * 设置路由
   */
  setupRoutes() {
    // 健康检查 - 保留用于监控
    this.app.get("/health", (req, res) => {
      res.json({
        status: "ok",
        timestamp: new Date().toISOString(),
      });
    });

    // 主代理路由
    this.app.use("*", this.proxyHandler.bind(this));
  }

  /**
   * 主代理处理函数
   */
  async proxyHandler(req, res, next) {
    const startTime = Date.now();

    try {
      // 跳过健康检查接口
      if (req.path === "/health") {
        return next();
      }

      // 基本输入验证
      if (!config.server.targetServer) {
        const error = new Error(
          "目标服务器未配置，请在.env文件中设置TARGET_SERVER"
        );
        error.status = 500;
        throw error;
      }

      // 并发数限制（不进行去重，让每个请求独立处理）
      const result = await this.rateLimiter.processRequest(
        `${req.method}_${Date.now()}_${Math.random()}`, // 确保每个请求都是唯一的
        async () => {
          return await this.handleRequest(req);
        }
      );

      // 设置响应头
      this.setResponseHeaders(res, result.headers);
      res.set("X-Cache-Hit", result.cacheHit ? "true" : "false");
      res.set("X-Response-Time", `${Date.now() - startTime}ms`);

      // 发送响应
      res.status(result.status).send(result.data);

      // 记录成功日志
      if (config.logging.enabled) {
        const size = result.data ? result.data.length : 0;
        // console.log(
        //   `✓ ${result.status} ${req.method} ${
        //     req.originalUrl
        //   } - ${this.formatBytes(size)} (${Date.now() - startTime}ms) [${
        //     result.cacheHit ? "缓存" : "新下载"
        //   }]`
        // );
        console.log(
          `✓ ${result.status} ${req.method} [${
            result.cacheHit ? "缓存" : "新下载"
          }]`
        );
      }
    } catch (error) {
      const duration = Date.now() - startTime;
      console.error(
        `✗ ${error.status || 500} ${req.method} ${req.originalUrl} - ${
          error.message
        } (${duration}ms)`
      );
      this.handleError(error, res);
    }
  }

  /**
   * 处理请求 - 核心逻辑
   */
  async handleRequest(req) {
    const needCache = this.cache.shouldCache(req.originalUrl);

    if (!needCache) {
      // 不需要缓存，直接代理
      return await this.forwardRequest(req);
    }

    const cacheKey = this.cache.generateCacheKey(req.originalUrl, {});

    // 尝试从缓存获取
    const isCacheValid = await this.cache.isCacheValid(cacheKey);
    
    if (isCacheValid) {
      // 解析Range请求
      let range = null;
      if (req.headers.range) {
        const rangeMatch = req.headers.range.match(/bytes=(\d+)-(\d+)?/);
        if (rangeMatch) {
          range = {
            start: parseInt(rangeMatch[1]),
            end: rangeMatch[2] ? parseInt(rangeMatch[2]) : undefined
          };
        }
      }
      
      const cachedData = await this.cache.getFromCache(cacheKey, range);
      if (cachedData) {
        // 如果是Range请求且缓存返回了Range数据
        if (cachedData.isRange && range) {
          const totalSize = 213359966; // 从文件统计中得到，后续可以优化
          return {
            data: cachedData.data,
            headers: {
              ...cachedData.headers,
              'content-length': cachedData.data.length.toString(),
              'content-range': `bytes ${range.start}-${range.end}/${totalSize}`,
              'accept-ranges': 'bytes',
            },
            status: 206,
            cacheHit: true,
          };
        }
        
        // 完整文件或者Range处理失败时的降级
        if (req.headers.range && !cachedData.isRange) {
          return this.handleCachedRangeRequest(req, cachedData);
        }
        
        return {
          data: cachedData.data,
          headers: {
            ...cachedData.headers,
            'accept-ranges': 'bytes',
          },
          status: cachedData.status,
          cacheHit: true,
        };
      }
    }

    // 缓存未命中，执行下载
    const targetUrl = config.server.targetServer + req.originalUrl;

    try {
      if (config.logging.enabled) {
        console.log(`🚀 流式缓存: ${this.getSimplePath(req.originalUrl)}`);
      }

      const saved = await this.cache.saveToCache(cacheKey, targetUrl, {
        "x-original-url": req.originalUrl,
        "x-has-range": req.headers.range ? "true" : "false",
      });

      if (saved) {
        const cachedData = await this.cache.getFromCache(cacheKey);
        if (cachedData) {
          return {
            data: cachedData.data,
            headers: cachedData.headers,
            status: cachedData.status,
            cacheHit: false,
            cached: true,
          };
        }
      }

      throw new Error("流式缓存保存失败");
    } catch (error) {
      // 流式缓存失败，使用直接代理作为降级方案
      console.warn(
        `⚠️ 流式缓存失败，使用直接代理: ${this.getSimplePath(
          req.originalUrl
        )} - ${error.message}`
      );

      // 清理可能的损坏缓存
      try {
        await this.cache.removeCacheFiles(cacheKey);
      } catch (cleanupError) {
        // 静默处理清理错误
      }

      return await this.forwardRequest(req);
    }
  }

  /**
   * 直接转发请求（统一使用原生HTTP模块）
   */
  async forwardRequest(req) {
    const targetUrl = config.server.targetServer + req.originalUrl;
    const forwardHeaders = this.buildForwardHeaders(req.headers);
    
    return await this.makeHttpRequest(targetUrl, {
      method: req.method,
      headers: forwardHeaders,
      body: req.method === "GET" ? undefined : req.body
    });
  }

  /**
   * 处理缓存的Range请求
   */
  handleCachedRangeRequest(req, cachedData) {
    const rangeHeader = req.headers.range;
    const rangeMatch = rangeHeader.match(/bytes=(\d+)-(\d+)?/);

    if (!rangeMatch) {
      // 无效的Range头，返回完整内容
      return {
        data: cachedData.data,
        headers: cachedData.headers,
        status: cachedData.status,
        cacheHit: true,
      };
    }

    const start = parseInt(rangeMatch[1]);
    const end = rangeMatch[2]
      ? parseInt(rangeMatch[2])
      : cachedData.data.length - 1;
    const totalSize = cachedData.data.length;

    // 验证Range范围
    if (start >= totalSize || end >= totalSize || start > end) {
      // 无效范围，返回416 Range Not Satisfiable
      return {
        data: Buffer.from("Range not satisfiable"),
        headers: {
          ...cachedData.headers,
          "content-range": `bytes */${totalSize}`,
        },
        status: 416,
        cacheHit: true,
      };
    }

    // 切片数据
    const slicedData = cachedData.data.slice(start, end + 1);
    const contentLength = slicedData.length;

    // 构建Range响应头
    const rangeHeaders = {
      ...cachedData.headers,
      "content-length": contentLength.toString(),
      "content-range": `bytes ${start}-${end}/${totalSize}`,
      "accept-ranges": "bytes",
    };

    return {
      data: slicedData,
      headers: rangeHeaders,
      status: 206, // Partial Content
      cacheHit: true,
    };
  }

  /**
   * 统一的HTTP请求方法（原生HTTP模块）
   */
  async makeHttpRequest(targetUrl, options = {}) {
    return new Promise((resolve, reject) => {
      const proto = targetUrl.startsWith("https") ? https : http;
      const agent = targetUrl.startsWith("https") ? this.httpsAgent : this.httpAgent;
      const urlObj = new URL(targetUrl);

      const requestOptions = {
        hostname: urlObj.hostname,
        port: urlObj.port,
        path: urlObj.pathname + urlObj.search,
        method: options.method || "GET",
        headers: options.headers || {},
        agent: agent,
      };

      const req = proto.request(requestOptions, (res) => {
        const chunks = [];
        let totalBytes = 0;

        res.on("data", (chunk) => {
          chunks.push(chunk);
          totalBytes += chunk.length;
        });

        res.on("end", () => {
          const data = Buffer.concat(chunks);

          resolve({
            data: data,
            headers: res.headers,
            status: res.statusCode,
            cacheHit: false,
          });
        });

        res.on("error", (error) => {
          reject(this.createHttpError(error, "响应错误"));
        });
      });

      req.on("error", (error) => {
        reject(this.createHttpError(error, "请求错误"));
      });

      req.setTimeout(30000, () => {
        req.destroy();
        reject(this.createHttpError(new Error("请求超时"), "超时"));
      });

      // 发送请求体（如果有）
      if (options.body && options.method !== "GET") {
        req.write(options.body);
      }

      req.end();
    });
  }

  /**
   * 创建统一的HTTP错误对象
   */
  createHttpError(error, type) {
    let enhancedError;
    
    if (error.code === "ETIMEDOUT" || type === "超时") {
      enhancedError = new Error("上游服务器超时");
      enhancedError.status = 504;
      enhancedError.timeout = true;
    } else if (error.code === "ENOTFOUND" || error.code === "ECONNREFUSED") {
      enhancedError = new Error("无法连接到上游服务器");
      enhancedError.status = 502;
      enhancedError.network = true;
    } else {
      enhancedError = new Error(`网络错误: ${error.message}`);
      enhancedError.status = 502;
      enhancedError.network = true;
    }
    
    return enhancedError;
  }

  /**
   * 构建转发请求头
   */
  buildForwardHeaders(originalHeaders) {
    const headers = { ...originalHeaders };

    // 修改host头部为目标服务器的host
    if (config.server.targetServer) {
      const targetUrl = new URL(config.server.targetServer);
      headers.host = targetUrl.host;
    }

    // 移除可能冲突的头部，但保留Range头用于分块下载
    delete headers.connection;
    delete headers["content-length"];
    delete headers["transfer-encoding"];

    // 保留重要的头部用于Range请求
    // range, if-range, if-modified-since 等应该保留

    return headers;
  }

  /**
   * 设置响应头（安全处理）
   */
  setResponseHeaders(res, headers) {
    if (!headers) return;

    // 对于Range请求，需要保留所有重要的响应头
    const safeHeaders = { ...headers };

    // 只删除可能冲突的连接相关头部
    delete safeHeaders.connection;
    delete safeHeaders["transfer-encoding"];

    // Range请求的关键头部必须保留：
    // - content-range (206响应必需)
    // - accept-ranges (告诉客户端支持range)
    // - content-length (部分内容的长度)
    // - content-type (保持原始类型)

    Object.keys(safeHeaders).forEach((key) => {
      try {
        res.set(key, safeHeaders[key]);
      } catch (error) {
        // 静默跳过无效的头部
      }
    });
  }

  /**
   * 获取简化的路径用于日志
   */
  getSimplePath(url) {
    try {
      const parsed = new URL(url, "http://localhost");
      const pathParts = parsed.pathname.split("/").filter((p) => p);
      const fileName = pathParts[pathParts.length - 1] || "unknown";
      return fileName.length > 50
        ? fileName.substring(0, 47) + "..."
        : fileName;
    } catch {
      return url.length > 50 ? url.substring(0, 47) + "..." : url;
    }
  }

  /**
   * 格式化字节大小
   */
  formatBytes(bytes) {
    if (bytes === 0) return "0B";
    const k = 1024;
    const sizes = ["B", "KB", "MB", "GB"];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + sizes[i];
  }

  /**
   * 错误处理
   */
  handleError(error, res) {
    if (res.headersSent) return;

    const status = error.status || 500;
    const errorResponse = {
      error: this.getErrorType(error),
      status,
      message: error.message,
      timestamp: new Date().toISOString(),
    };

    // 在开发环境下提供更多调试信息
    if (process.env.NODE_ENV !== "production") {
      errorResponse.type = error.constructor.name;
      if (error.upstream) errorResponse.upstream = true;
      if (error.timeout) errorResponse.timeout = true;
      if (error.network) errorResponse.network = true;
    }

    res.status(status).json(errorResponse);
  }

  /**
   * 获取错误类型描述
   */
  getErrorType(error) {
    if (error.upstream) return "上游服务器错误";
    if (error.timeout) return "请求超时";
    if (error.network) return "网络连接错误";
    if (error.status >= 400 && error.status < 500) return "客户端错误";
    return "内部服务器错误";
  }

  /**
   * 启动服务器
   */
  start() {
    const PORT = config.server.port;

    this.server = this.app.listen(PORT, () => {
      console.log(`\n🚀 优化的点云缓存代理服务器已启动`);
      console.log(`📡 监听端口: ${PORT}`);
      console.log(`🎯 目标服务器: ${config.server.targetServer || "未配置"}`);
      console.log(`💾 缓存目录: ${config.cache.dir}`);
      console.log(`🔧 最大并发: ${config.rateLimiting.maxConcurrentRequests}`);
      console.log(`⏱️  超时设置: 30秒`);
      console.log(`🔄 连接复用: 启用`);
      console.log(`\n✅ 服务器就绪，等待请求...\n`);
    });

    // 设置服务器超时
    this.server.timeout = 120000; // 2分钟
    this.server.keepAliveTimeout = 65000; // 65秒
    this.server.headersTimeout = 66000; // 66秒

    // 优雅关闭
    this.setupGracefulShutdown();
  }

  /**
   * 设置优雅关闭
   */
  setupGracefulShutdown() {
    const shutdown = async (signal) => {
      console.log(`\n收到 ${signal} 信号，开始优雅关闭...`);

      // 停止接受新连接
      this.server.close(() => {
        console.log("HTTP服务器已关闭");
      });

      // 清理资源
      try {
        if (this.httpsAgent) {
          this.httpsAgent.destroy();
          console.log("HTTPS连接池已清理");
        }
        
        if (this.httpAgent) {
          this.httpAgent.destroy();
          console.log("HTTP连接池已清理");
        }

        // 停止缓存定期清理任务（如果启用了的话）
        if (this.cache && this.cache.periodicCleanupEnabled) {
          this.cache.stopPeriodicCleanup();
        }
      } catch (error) {
        console.warn("资源清理时出现警告:", error.message);
      }

      // 等待活跃连接完成（最多10秒）
      setTimeout(() => {
        console.log("强制退出");
        process.exit(0);
      }, 10000);
    };

    process.on("SIGINT", () => shutdown("SIGINT"));
    process.on("SIGTERM", () => shutdown("SIGTERM"));

    // 处理未捕获的异常
    process.on("uncaughtException", (error) => {
      console.error("未捕获的异常:", error);
      shutdown("uncaughtException");
    });

    process.on("unhandledRejection", (reason, promise) => {
      console.error("未处理的Promise拒绝:", reason);
      shutdown("unhandledRejection");
    });
  }
}

// 启动应用
if (require.main === module) {
  const server = new ProxyServer();
  server.start();
}

module.exports = ProxyServer;
